import configparser

import datetime

import json

import socket

import sys

import time

from PyQt5 import QtCore, QtWidgets

from Ui_main_window import Ui_MainWindow

from tdr import CALLBACK_CMD, RECEIVE_ERROR, RECEIVE_SUCCES, STATUSBAR_MESSAGE
from tdr import ERRMSGSRC_LOGIN, ERRMSGSRC_MARKETSTATE, SH, SZ
from tdr import MARKET_STATE_BREAK, MARKET_STATE_CLOSE
from tdr import SUBSCRIBE_FAIL, SUBSCRIBE_SUCCESS

RED = "color: rgb(255, 0, 0);"
GREEN = "color: rgb(0, 255, 0);"
WHITE = "color: rgb(255, 255, 255);"


class MarketLinkthread(QtCore.QThread):
    _signal = QtCore.pyqtSignal(dict)
    # receive_buff = ""

    def __init__(self, sock):
        super(MarketLinkthread, self).__init__()
        self.dict_msg = {}
        self.sock = sock
        self.event = False
        self.subscribed = False
        self.dict_subs = {}
        cf = configparser.ConfigParser()
        cf.read("client_config.ini")
        # 正式服务器用配置
        # self.ini_section = "server"
        # 测试服务器用配置
        self.ini_section = cf.get("default", "default_section")
        self.server_ip = cf.get(self.ini_section, "ip")
        self.server_port = int(cf.get(self.ini_section, "port"))
        print('连接到 %s:%s...' % (self.server_ip, self.server_port))
        self.log_file('连接到 %s:%s...' % (self.server_ip, self.server_port))

    def __del__(self):
        self.sock.close()
        self.wait()

    def run(self):
        self.log_file('in run():')
        time.sleep(0.01)
        try:
            self.sock.connect((self.server_ip, self.server_port))
        except:
            self.log_file('Socket异常断开！')
        else:
            self.dict_msg["event_type"] = STATUSBAR_MESSAGE
            self.dict_msg["message"] = ("已连接到服务器 %s:%s" % (self.server_ip,
                                        self.server_port))
            self._signal.emit(self.dict_msg)
            self.log_file('更新状态条信息：%s' % self.dict_msg["message"])
            self.dict_msg = {}
            while True:
                array_data = self.recv_basic(self.sock)
                # self.log_file('收取数据完成，在主循环体中。receive_data=%s' % array_data)
                for data in array_data:
                    json_data = json.loads(data)
                    self.dict_msg = json_data
                    self._signal.emit(self.dict_msg)
                    # self.log_file('发送数据 %s 回窗体' % self.dict_msg)
                    self.dict_msg = {}
                # 发送完成后，回送订阅请求
                if self.subscribed:
                    send_data = json.dumps(self.dict_subs).encode('utf-8')
                    self.sock.sendall(send_data)
                    self.dict_subs = {}
                    self.subscribed = False
                time.sleep(0.1)

    def split_strings(self, input_bytes):
        full_str = input_bytes.decode('utf-8')
        i = 0
        tmp_str = ""
        array_str = []
        while i < len(full_str):
            tmp_str += full_str[i]
            if full_str[i] == '}':
                array_str.append(tmp_str)
                tmp_str = ""
            i += 1
        return array_str

    def recv_basic(self, the_socket):
        total_data = []
        while True:
            data = the_socket.recv(1024)
            # print('in recv_basic: 收到Data：%s' % data)
            # self.log_file('in recv_basic: 收到Data：%s' % data)
            if len(data) < 1024:
                total_data.append(data)
                # print('data 长度为 %s，数据收取完成，准备合并各个片段' % len(data))
                # self.log_file('data 长度为 %s，数据收取完成，准备合并各个片段' % len(data))
                break
            else:
                total_data.append(data)
        receive_data = b''.join(total_data)
        array_data = self.split_strings(receive_data)
        # self.log_file('return_data: %s' % array_data)
        return array_data

    def subscribe_action(self, dict_msg):
        self.dict_subs = dict_msg
        self.dict_subs['event_type'] = CALLBACK_CMD
        self.subscribed = True
        self.log_file('收到订阅事件，已设定好标志，等待发送：event:%s, msg=%s'
                      '' % (self.subscribed, self.dict_subs))

    def log_file(self, log_str):
        str_dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        str_dt2 = datetime.datetime.now().strftime("%Y-%m-%d")
        log_filename = 'client_%s.log' % str_dt2
        with open(log_filename, 'a', encoding='utf-8') as my_logfile:
            log_str = '%s %s' % (str_dt, log_str)
            my_logfile.write(log_str + '\n')


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.lineEdit.returnPressed.connect(self.query_action)
        self.label_name.setText('名称')
        self.label_code.setText('代码')
        self.log_file('====================程序开始运行！====================')
        self.sCode = '510900'
        self.sMarket = 'SH'
        self.statusbar.showMessage("应用程序就绪")
        self.ask_price = [0 for i in range(10)]
        self.ask_vol = [0 for i in range(10)]
        self.bid_price = [0 for i in range(10)]
        self.bid_vol = [0 for i in range(10)]
        self.ask_price_last = [0 for i in range(10)]
        self.ask_vol_last = [0 for i in range(10)]
        self.bid_price_last = [0 for i in range(10)]
        self.bid_vol_last = [0 for i in range(10)]
        data_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        data_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self._thread = MarketLinkthread(data_socket)
        self._thread._signal.connect(self.callback_update)
        self._thread.start()

    def callback_update(self, dict_msg):
        if dict_msg:
            self.log_file('窗体接受到 emit 事件！%s' % dict_msg)
            if dict_msg['event_type']:
                if dict_msg['event_type'] == RECEIVE_SUCCES:
                    sCode = dict_msg['sCode']
                    # 推送的行情是窗口当前订阅的代码
                    if sCode == self.sCode:
                        self.label_code.setText(dict_msg['sCode'])
                        self.label_name.setText(dict_msg['sName'])
                        # self.log_file("窗体收到数据推送：信息是 %s" % dict_msg)

                        if sCode[0] in ['5', '1']:
                            uPreClose = str('%.3f' % (
                                dict_msg['uPreClose'] / 10000))
                        else:
                            uPreClose = str('%.2f' % (
                                dict_msg['uPreClose'] / 10000))
                        # self.log_file("uPreClose=%s" % uPreClose)

                        for i in range(10):
                            # ETF类别，保留三位小数
                            if sCode[0] == '5':
                                self.ask_price[i] = str('%.3f' % (
                                    dict_msg['ask_price_%s' % i] / 10000))
                                self.bid_price[i] = str('%.3f' % (
                                    dict_msg['bid_price_%s' % i] / 10000))
                                self.ask_vol[i] = (dict_msg['ask_vol_%s' % i]
                                                   // 100)
                                self.bid_vol[i] = (dict_msg['bid_vol_%s' % i]
                                                   // 100)
                            # 转债类别，保留三位小数
                            elif sCode[0] == '1':
                                self.ask_price[i] = str('%.3f' % (
                                    dict_msg['ask_price_%s' % i] / 10000))
                                self.bid_price[i] = str('%.3f' % (
                                    dict_msg['bid_price_%s' % i] / 10000))
                                self.ask_vol[i] = dict_msg['ask_vol_%s' % i]
                                self.bid_vol[i] = dict_msg['bid_vol_%s' % i]
                            # 证券价格，保留两位小数
                            else:
                                self.ask_price[i] = str('%.2f' % (
                                    dict_msg['ask_price_%s' % i] / 10000))
                                self.bid_price[i] = str('%.2f' % (
                                    dict_msg['bid_price_%s' % i] / 10000))
                                self.ask_vol[i] = (dict_msg['ask_vol_%s' % i]
                                                   // 100)
                                self.bid_vol[i] = (dict_msg['bid_vol_%s' % i]
                                                   // 100)

                            # 为内容填充数值
                            object_ask_label = self.findChild(
                                (QtWidgets.QLabel, ), ('label_ask_price_%s'
                                                       '' % (i + 1)))
                            if object_ask_label:
                                object_ask_label.setText(self.ask_price[i])

                            object_ask_vol = self.findChild(
                                (QtWidgets.QLabel, ), ('label_ask_vol_%s'
                                                       '' % (i + 1)))
                            if object_ask_vol:
                                object_ask_vol.setText(str(self.ask_vol[i]))

                            object_bid_label = self.findChild(
                                (QtWidgets.QLabel, ), ('label_bid_price_%s'
                                                       '' % (i + 1)))
                            if object_bid_label:
                                object_bid_label.setText(self.bid_price[i])

                            object_bid_vol = self.findChild(
                                (QtWidgets.QLabel, ), ('label_bid_vol_%s'
                                                       '' % (i + 1)))
                            if object_bid_vol:
                                object_bid_vol.setText(str(self.bid_vol[i]))

                            # 设置颜色
                            # self.log_file(self.ask_price[i])
                            if self.ask_price[i] == uPreClose:
                                object_ask_label.setStyleSheet(WHITE)
                            elif float(self.ask_price[i]) < float(uPreClose):
                                object_ask_label.setStyleSheet(GREEN)
                            else:
                                object_ask_label.setStyleSheet(RED)

                            if self.bid_price[i] == uPreClose:
                                object_bid_label.setStyleSheet(WHITE)
                            elif float(self.bid_price[i]) < float(uPreClose):
                                object_bid_label.setStyleSheet(GREEN)
                            else:
                                object_bid_label.setStyleSheet(RED)

                            object_label = self.findChild(
                                (QtWidgets.QLabel, ), ('label_ask_change_%s'
                                                       '' % (i + 1)))
                            if object_label:
                                object_label.setText("")
                                if self.ask_price[i] in self.ask_price_last:
                                    vol_index = self.ask_price_last.index(
                                        self.ask_price[i])
                                    vol_diff = (self.ask_vol[i] -
                                                self.ask_vol_last[vol_index])
                                    if abs(vol_diff) >= 1:
                                        if vol_diff > 0:
                                            object_label.setText(
                                                '+%s' % str(vol_diff))
                                            object_label.setStyleSheet(RED)
                                        else:
                                            object_label.setText(str(vol_diff))
                                            object_label.setStyleSheet(GREEN)

                            object_label = self.findChild(
                                (QtWidgets.QLabel, ), ('label_bid_change_%s'
                                                       '' % (i + 1)))
                            if object_label:
                                object_label.setText("")
                                if self.bid_price[i] in self.bid_price_last:
                                    vol_index = self.bid_price_last.index(
                                        self.bid_price[i])
                                    vol_diff = (self.bid_vol[i] -
                                                self.bid_vol_last[vol_index])
                                    if abs(vol_diff) >= 1:
                                        if vol_diff > 0:
                                            object_label.setText(
                                                '+%s' % str(vol_diff))
                                            object_label.setStyleSheet(RED)
                                        else:
                                            object_label.setText(str(vol_diff))
                                            object_label.setStyleSheet(GREEN)
                        self.ask_price_last = self.ask_price[:]
                        self.ask_vol_last = self.ask_vol[:]
                        self.bid_price_last = self.bid_price[:]
                        self.bid_vol_last = self.bid_vol[:]
                        str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                        self.statusbar.showMessage('%s 收到行情数据推送' % str_dt)

                elif dict_msg['event_type'] == RECEIVE_ERROR:
                    str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                    nError = dict_msg['nError']
                    nErrSource = dict_msg['nErrSource']
                    uData = dict_msg['uData']
                    if (nErrSource == ERRMSGSRC_MARKETSTATE and
                       uData == MARKET_STATE_BREAK and nError == SH):
                        self.log_file('收到沪市休市信号。')
                        self.statusbar.showMessage('%s 收到沪市休市信号。' % str_dt)
                    if (nErrSource == ERRMSGSRC_MARKETSTATE and
                       uData == MARKET_STATE_CLOSE and nError == SH):
                        self.log_file('收到沪市闭市信号。')
                        self.statusbar.showMessage('%s 收到沪市闭市信号。' % str_dt)
                    if (nErrSource == ERRMSGSRC_MARKETSTATE and
                       uData == MARKET_STATE_BREAK and nError == SZ):
                        self.log_file('收到深市休市信号。')
                        self.statusbar.showMessage('%s 收到深市休市信号。' % str_dt)
                    if (nErrSource == ERRMSGSRC_MARKETSTATE and
                       uData == MARKET_STATE_CLOSE and nError == SZ):
                        self.log_file('收到深市闭市信号。')
                        self.statusbar.showMessage('%s 收到深市闭市信号。' % str_dt)
                    if nErrSource == ERRMSGSRC_LOGIN:
                        self.log_file('收到行情服务器停止信号。')
                        self.statusbar.showMessage('%s 收到行情服务器停止信号。' % str_dt)

                elif dict_msg['event_type'] == SUBSCRIBE_SUCCESS:
                    self.sCode = dict_msg['sCode']
                    self.sMarket = dict_msg['sMarket']
                    message = ('证券代码 %s.%s 订阅成功！当前证券显示代码已切换。'
                               '' % (self.sCode, self.sMarket))
                    self.log_file(message)
                    self.statusbar.showMessage(message)
                    str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                    self.statusbar.showMessage('%s 行情订阅成功！' % str_dt)

                elif dict_msg['event_type'] == SUBSCRIBE_FAIL:
                    message = '证券代码 %s 订阅失败！当前证券显示代码为 %s.%s' % (
                        dict_msg['sCode'], self.sCode, self.sMarket)
                    self.log_file(message)
                    self.statusbar.showMessage(message)
                    str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                    self.statusbar.showMessage('%s 行情订阅失败！' % str_dt)

                elif dict_msg['event_type'] == STATUSBAR_MESSAGE:
                    message = dict_msg['message']
                    self.statusbar.showMessage(message)

    def log_file(self, log_str):
        str_dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        str_dt2 = datetime.datetime.now().strftime("%Y-%m-%d")
        log_filename = 'client_%s.log' % str_dt2
        with open(log_filename, 'a', encoding='utf-8') as my_logfile:
            log_str = '%s %s' % (str_dt, log_str)
            my_logfile.write(log_str + '\n')

    def query_action(self):
        user_input = self.lineEdit.text().lower()
        self.lineEdit.setText("")
        dict_msg = {}
        dict_msg['user_input'] = user_input
        dict_msg['sCode'] = self.sCode
        dict_msg['sMarket'] = self.sMarket
        self.log_file("触发订阅事件！详细内容：%s" % dict_msg)
        self._thread.subscribe_action(dict_msg)

    def clear_volchange_labels(self):
        for i in range(10):
            object_label = self.findChild(
                (QtWidgets.QLabel, ), 'label_ask_change_%s' % (i + 1))
            if object_label:
                object_label.setText("")
            object_label = self.findChild(
                (QtWidgets.QLabel, ), 'label_bid_change_%s' % (i + 1))
            if object_label:
                object_label.setText("")


if __name__ == '__main__':
    APP = QtWidgets.QApplication(sys.argv)
    UI = MainWindow()
    UI.show()
    APP.exec_()
